/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.web.bean.lookup;

import com.jb.faces.el.AttributeEvaluator;
import com.jb.framework.DataSourceManager;
import com.jb.framework.datasource.TableModel;
import com.jb.framework.util.PropUtil;
import com.jb.util.Meter;
import com.jb.web.application.ApplicationImpl;
import com.jb.web.context.WebContext;

import java.io.File;
import java.io.FileInputStream;

import java.sql.Connection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Move all this to a resource file
 */
public class LookupBase extends TableModel {
    static private Log log = LogFactory.getLog(LookupBase.class.getName());
    static final private HashMap hashedOptions = new HashMap();
    static{
        init();
    }
    static void init()
    {
        Meter.start();
        String[][] bOptions = {
                { "True", "true" },
                { "False", "false" }
            };

        register("boolean", bOptions);

        String[][] bAccess = {
                { "Private", "0" },
                { "Public", "2" },
                { "Friend", "1" }
            };

        register("access", bAccess);

        String[][] pageAccess = {
                { "Private", "private" },
                { "Restrict", "restrict" },
                { "Public", "public" },
                { "Group", "group" }
            };

        register("pageAccess", pageAccess);

        String[] a1 = new String[] { "00", "22", "44", "66", "88", "AA", "CC", "EE", "FF" };
        ArrayList arrayList = new ArrayList();

        for (int i = 0; i < a1.length; i++) {
            for (int j = 0; j < a1.length; j++) {
                for (int k = 0; k < a1.length; k++) {
                    arrayList.add("#" + a1[i] + a1[j] + a1[k]);
                }
            }
        }

        //gray
        for (int i = 0; i < 16; i += 2) {
            for (int k = 0; k < 16; k += 2) {
                String a = "#" + Integer.toHexString(i + 1) + Integer.toHexString(k) + Integer.toHexString(i + 1) +
                    Integer.toHexString(k) + Integer.toHexString(i + 1) + Integer.toHexString(k);
                arrayList.add(a.toUpperCase());
            }
        }

        String[][] colorOptions = new String[arrayList.size()][2];

        for (int i = 0; i < arrayList.size(); i++) {
            colorOptions[i][0] = (String) arrayList.get(i);
            colorOptions[i][1] = (String) arrayList.get(i);
        }

        register("color", colorOptions);

        String[][] cursorOptions = {
                { "None", "" },
                { "Default", "default" },
                { "CrossHair", "CrossHair" },
                { "Pointer", "pointer" },
                { "Move", "move" },
                { "Text", "text" },                
                { "Wait", "wait" },
                
                { "Progress", "progress" },
                { "Resize", "resize" },
                { "Col Resize", "col-resize" },
                { "Row Resize", "row-resize" },
                { "Not Allowed", "no-drop" },
                
                { "Help", "help" }
            };

        //auto, crosshair, default, 
       // pointer, move, text, wait, progress, help, resize, e-resize, ne-resize, 
       // nw-resize, n-resize, se-resize, sw-resize, s-resize, w-resize, row-resize, 
       // col-resize, vertical-text, all-scroll, no-drop, not-allowed

        register("cursor", cursorOptions);

        String[][] displayOption = {
                { "Default", "" },
                { "Inline", "inline" },
                { "Block", "block" },
                { "Inline-Block", "inline-block" },
                { "Run-In", "run-in" },
                { "List-Item", "list-item" },
                { "None", "none" }
            };

        register("displayStyle", displayOption);

        String[][] sqlDataType = {
                { "VARCHAR", "VARCHAR" },
                { "TINYINT", "TINYINT" },
                { "TEXT", "TEXT" },
                { "DATE", "DATE" },
                { "SMALLINT", "SMALLINT" },
                { "MEDIUMINT", "MEDIUMINT" },
                { "INT", "INT" },
                { "BIGINT", "BIGINT" },
                { "FLOAT", "FLOAT" },
                { "DOUBLE", "DOUBLE" },
                { "DECIMAL", "DECIMAL" },
                { "DATETIME", "DATETIME" },
                { "TIMESTAMP", "TIMESTAMP" },
                { "TIME", "TIME" },
                { "YEAR", "YEAR" },
                { "CHAR", "CHAR" },
                { "TINYBLOB", "TINYBLOB" },
                { "TINYTEXT", "TINYTEXT" },
                { "BLOB", "BLOB" },
                { "MEDIUMBLOB", "MEDIUMBLOB" },
                { "MEDIUMTEXT", "MEDIUMTEXT" },
                { "LONGBLOB", "LONGBLOB" },
                { "LONGTEXT", "LONGTEXT" },
                { "ENUM", "ENUM" },
                { "SET", "SET" },
                { "BOOL", "BOOL" },
                { "BINARY", "BINARY" },
                { "VARBINARY", "VARBINARY" }
            };

        register("mySqlDataType", sqlDataType);

        //                "static:private,Private;Friends,friends;public,Public;"));
        String[][] floatOption = {
                { "Default", "" },
                { "Left", "left" },
                { "Right", "right" }
            };

        register("floatOption", floatOption);

        String[][] repeatInterval = {
                { "Do Not Repeat", "0" },
                { "Daily", "1" },
                { "Weekly", "2" },
                { "Monthly", "3" },
                { "Yearly", "4" }
            };

        register("repeatInterval", repeatInterval);

        //revealshape
        String[][] transitionShapeOptions = {
                { "Box In", "0" },
                { "Box Out", "1" },
                { "Circle In", "2" },
                { "Circle Out", "3" },
                { "Wipe Up", "4" },
                { "Wipe Down", "5" },
                { "Wipe Right", "6" },
                { "Wipe Left", "7" },
                { "Vertical Blinds", "8" },
                { "Horizontal Blinds", "9" },
                { "CheckerBoard Across", "10" },
                { "CheckerBoard Down", "11" },
                { "Random Dissolve", "12" },
                { "Split Vertical In", "13" },
                { "Split Vertical Out", "14" },
                { "Split Horizontal In", "15" },
                { "Split Horizontal Out", "16" },
                { "Strips Left Down", "17" },
                { "Strips Left Up", "18" },
                { "Strips Right Down", "19" },
                { "Strips Right Up", "20" },
                { "Random Bars Horizontal", "21" },
                { "Random Bars Vertical", "22" },
                { "Random", "23" }
            };

        register("transitionShape", transitionShapeOptions);

        String[][] namedColors = {
                { "None", "" },
                { "Transparent", "transparent" },
                { "Black", "black" },
                { "Silver", "silver" },
                { "Gray", "gray" },
                { "White", "white" },
                { "Maroon", "maroon" },
                { "Red", "red" },
                { "Purple", "purple" },
                { "Fuchsia", "fuchsia" },
                { "Lime", "lime" },
                { "Olive", "olive" },
                { "Yellow", "yellow" },
                { "Navy", "navy" },
                { "Blue", "blue" },
                { "Teal", "teal" },
                { "Aqua", "aqua" }
            };

        register("namedColors", namedColors);

        //border style
        String[][] borderStyle = {
                { "None", "" },
                { "solid", "solid" },
                { "dashed", "dashed" },
                { "dotted", "dotted" },
                { "double", "double" },
                { "groove", "groove" },
                { "inset", "inset" },
                { "outset", "outset" },
                { "ridge", "ridge" }
            };

        register("borderStyle", borderStyle);

        //align stype
        String[][] cellAlign = {
                { "None", "" },
                { "Center", "center" },
                { "Left", "left" },
                { "Right", "right" }
            };

        register("cellAlign", cellAlign);

        String[][] textAlignOptions = {
                { "None", "" },
                { "Center", "Center" },
                { "Left", "Left" },
                { "Right", "Right" },
                { "justify", "Justify" }
            };

        register("align", textAlignOptions);

        String[][] vCellAlign = {
                { "None", "" },
                { "Top", "top" },
                { "Middle", "middle" },
                { "Bottom", "bottom" }
            };

        register("vCellAlign", vCellAlign);

        String[][] valign = {
                { "None", "" },
                { "Top", "top" },
                { "Middle", "middle" },
                { "Bottom", "bottom" },
                { "Base Line", "baseline" },
                { "Superscript", "super" },
                { "Subscript", "sub" },
                { "Text top", "text-top" },
                { "Text bottom", "text-bottom" }
            };

        register("valign", valign);

        String[][] position = {
                { "Default", "" },
                { "Absolute", "absolute" },
                { "Relative", "relative" },
                { "Fixed", "fixed" },
                { "Default", "baseline" }
            };

        register("position", position);

        String[][] floatStyle = {
                { "Default", "" },
                { "Right", "right" },
                { "Left", "left" }
            };

        register("floatStyle", floatStyle);

        String[][] overflow = {
                { "Default", "" },
                { "auto", "auto" },
                { "scroll", "scroll" },
                { "hide", "hide" },
                { "show", "show" }
            };

        register("overflow", overflow);
/*
        String[] timeZone = TimeZone.getAvailableIDs();
        TableModel tdo = new TableModel(timeZone);
        hashedOptions.put("timeZone", tdo);

        Locale[] locales = Locale.getAvailableLocales();
        String[] languages = new String[locales.length];

        for (int i = 0; i < locales.length; i++) {
            languages[i] = locales[i].toString();
        }

        tdo = new TableModel(languages);
        hashedOptions.put("language", tdo);
*/
        String[][] userEvent = {
                { "Update", "update" },
                { "Create", "create" },
                { "Delete", "delete" }
            };

        register("userEvent", userEvent);

        String[][] scope = {
                { "Request", "request" },
                { "Session", "session" },
                { "Application", "application" }
            };

        register("scope", scope);

        String[][] permission = {
                { "Private", "private" },
                { "Group", "group" },
                { "Public", "public" }
            };

        register("permission", permission);

        String[][] wrap = {
                { "Auto", "" },
                { "No Wrap", "NOWRAP" }
            };

        register("wrap", wrap);
        Meter.stop("initialize LookupBase");
    }
    public static void main(String[] args) {
        
    }
    /**
     *
     *
     * @param dataSourceType parameter
     * @param keyString parameter
     *
     * @return return-value
     */
    public static TableModel getLookupData(WebContext ctx, String dataSourceType, String keyString, String format) {
        Meter.start();
        try
        {
        if (dataSourceType.equalsIgnoreCase("sql")) {
            return populateOptionData(keyString);
        } else if (dataSourceType.equalsIgnoreCase("static")) {
            return staticOptionData(keyString);
        } else if (dataSourceType.equalsIgnoreCase("file")) {
            return populateFromFile(ctx, keyString);
        } else if (dataSourceType.equalsIgnoreCase("el")) {
            return populateFromEl(ctx, keyString, format);
        } else {
            return (TableModel) hashedOptions.get(keyString);
        }}finally {
            Meter.stop(LookupBase.class.getName() +" "+dataSourceType + " "+ keyString);
        }
    }

    public static void register(String name, String[][] tb) {
        TableModel tdo = TableModel.getTableDataObject(tb);
        hashedOptions.put(name, tdo);
    }

    static private TableModel assignOptionData(String[][] tableData)
        throws Exception {
        return TableModel.getTableDataObject(tableData);
    }

    //allowing option to have a sql statement 
    static private TableModel populate(String sqlStmt)
        throws Exception {
        if (sqlStmt == null) {
            throw new Exception("No SQL statement specified!");
        }

        Connection conn = null;

        try {
            conn = DataSourceManager.getConnection(com.jb.web.bean.lookup.LookupBase.class);

            SqlTableObject sqlObj = new SqlTableObject(sqlStmt);
            sqlStmt = sqlObj.getSelectStmt();
            sqlObj.update(conn);

            TableModel tableData = sqlObj.getTableData();
            sqlObj = null;

            return tableData;
        } finally {
            DataSourceManager.releaseConnection(com.jb.web.bean.lookup.LookupBase.class, conn);
        }
    }

    static private TableModel populateFromFile(WebContext pCtx, String fileStmt) {
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream(com.jb.resource.ResourceManager.getResourcePath(pCtx) + File.separator +
                    fileStmt));

            return new TableModel(properties);
        } catch (Exception e) {
            e.printStackTrace();
            pCtx.addErrorMessage(pCtx, "Can not load property file " + fileStmt);
        }

        return null;
    }


    static private TableModel populateFromEl(WebContext pCtx, String exp, String format) {
        try {
            Object object = AttributeEvaluator.evaluate(pCtx, null, exp);
            if(object instanceof List)
            {
                if(format==null || format.length()==0)
                    return new TableModel((List)object, (List)object);
                else {
                    String[] propNames=format.trim().split(",");
                    List list = (List) object;
                    List values = new ArrayList();
                    List names = new ArrayList();
                    for(int i = 0 ; i< list.size();i++) {
                        Object obj = list.get(i);
                        names.add(PropUtil.getProperty(obj, propNames[0]));
                        values.add(PropUtil.getProperty(obj, propNames[1]));
                    }
                    return new TableModel(names, values);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            pCtx.addErrorMessage(pCtx, "Failed to load value options " + exp);
        }

        return null;
    }

    static private TableModel populateOptionData(String optionStr) {
        try {
            return populate(optionStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    static private TableModel staticOptionData(String optionStr) {
        try {
            StringTokenizer st = new StringTokenizer(optionStr, ";");
            ArrayList nameList = new ArrayList();
            ArrayList valueList = new ArrayList();

            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                String value = token.substring(0, token.indexOf(","));
                String key = token.substring(token.indexOf(",") + 1, token.length());
                nameList.add(key);
                valueList.add(value);
            }

            String[][] options = new String[nameList.size()][2];

            for (int i = 0; i < nameList.size(); i++) {
                options[i][0] = (String) nameList.get(i);
                options[i][1] = (String) valueList.get(i);
            }

            return assignOptionData(options);
        } catch (Exception e) {
            if(log.isErrorEnabled())
                log.error(e);
        }
        return null;
    }
}
